<template>
  <div>
    <div ref="mapDiv" class="full-height full-width" />
    <!--底部选项-->
    <transition-fade>
      <div
        @mouseup="pixiMap.outStage"
        style="height: 50px"
        :class="ui.modelClass"
        class="absolute-bottom full-width justify-center flex"
        v-if="editMode === ''"
      >
        <q-btn-dropdown
          split
          no-caps
          rounded
          :class="ui.btnClass"
          :label="mode === 'relocate' ? '设备定位' : '手动定位'"
          unelevated
          style="margin: auto 15px"
          v-show="showRobot"
          @click="editMode = 'relocate'"
        >
          <q-list>
            <q-item
              clickable
              v-close-popup
              v-for="item in optionsMode"
              v-bind:key="item"
              @click="mode = item.value"
            >
              <q-item-section :class="mode === item.value ? 'text-blue' : ''">
                <q-item-label>{{ item.label }}</q-item-label>
              </q-item-section>
            </q-item>
          </q-list>
        </q-btn-dropdown>
        <q-btn
          no-caps
          rounded
          unelevated
          style="margin: auto 15px"
          :class="ui.btnClass"
          :label="$t('MapEdit.点位设定')"
          @click="editMode = 'point'"
        />
        <q-btn
          no-caps
          rounded
          unelevated
          style="margin: auto 15px"
          :class="ui.btnClass"
          :label="$t('MapEdit.安全区域')"
          @click="editMode = 'polygon'"
        />
        <q-btn
          no-caps
          rounded
          unelevated
          style="margin: auto 15px"
          :class="ui.btnClass"
          :label="t('MapCreate.远程遥控')"
          v-show="showRobot"
          @click="showQrCode"
        />
      </div>
    </transition-fade>
    <!--顶部选项-->
    <div
      class="absolute full-width orientation-portrait"
      style="top: 50px"
      @mouseup="pixiMap.outStage"
    >
      <!--列表-->
      <transition-fade>
        <list-edit-small
          v-if="editMode && mode !== 'manual'"
          :list="editMode === 'polygon' ? polygonList : pointList"
          ref="pointInSmall"
          :active-id="activePoint.hasOwnProperty('id') ? activePoint.id : ''"
          @exit="exit"
          @choose="choose"
          @add="add"
          :needAdd="editMode === 'point' || editMode === 'polygon'"
        />
      </transition-fade>
      <!--修改弹窗-->
      <transition-fade>
        <input-in-small
          v-show="
            editMode !== 'polygon' && editType === 'edit' && mode !== 'manual'
          "
          :label="$t('MapEdit.点位名称')"
          v-model="activePoint.name"
        >
          <q-btn-dropdown flat style="width: 50px">
            <div :class="ui.headerClass">
              <q-list>
                <q-item
                  clickable
                  v-close-popup
                  @click="pointEdit.show(activePoint)"
                >
                  <q-item-section>
                    <q-item-label class="text-space text-center"
                      >编辑</q-item-label
                    >
                  </q-item-section>
                </q-item>
                <q-item
                  v-show="showRobot"
                  clickable
                  v-close-popup
                  @click="relocatePoint(activePoint)"
                >
                  <q-item-section>
                    <q-item-label class="text-space text-center">{{
                      $t("MapEdit.重定位")
                    }}</q-item-label>
                  </q-item-section>
                </q-item>
                <q-item
                  clickable
                  v-close-popup
                  @click="deletePoint(activePoint)"
                >
                  <q-item-section>
                    <q-item-label class="text-space text-center text-red">{{
                      $t("del")
                    }}</q-item-label>
                  </q-item-section>
                </q-item>
              </q-list>
            </div>
          </q-btn-dropdown>
        </input-in-small>
      </transition-fade>
    </div>
    <!--左侧选项-->
    <div
      class="absolute orientation-landscape"
      style="top: 50px; height: calc(100vh - 50px)"
      @mouseup="pixiMap.outStage"
    >
      <!--列表-->
      <transition-fade>
        <list-edit-big
          v-if="editMode && mode !== 'manual'"
          ref="pointInBig"
          :title="listTitle"
          :list="editMode === 'polygon' ? polygonList : pointList"
          :active-id="activePoint.hasOwnProperty('id') ? activePoint.id : ''"
          @exit="exit"
          @choose="choose"
          @add="add"
          :needAdd="editMode === 'point' || editMode === 'polygon'"
        >
          <q-btn
            no-caps
            icon="more_vert"
            flat
            @click.stop.prevent
            v-if="editMode !== 'polygon'"
          >
            <q-menu
              :dark="ui.isDark"
              transition-show="jump-down"
              transition-hide="jump-up"
            >
              <q-list style="min-width: 140px; letter-spacing: 2px">
                <q-item
                  clickable
                  v-close-popup
                  @click="pointEdit.show(activePoint)"
                >
                  <q-item-section>
                    <q-icon name="edit" size="sm" color="primary" />
                  </q-item-section>
                  <q-item-section> 编辑 </q-item-section>
                </q-item>
                <q-item
                  clickable
                  v-close-popup
                  @click="relocatePoint(activePoint)"
                >
                  <q-item-section>
                    <q-icon name="place" size="sm" color="primary" />
                  </q-item-section>
                  <q-item-section> 重定位 </q-item-section>
                </q-item>
                <q-item
                  clickable
                  v-close-popup
                  @click="deletePoint(activePoint)"
                >
                  <q-item-section>
                    <q-icon name="delete" size="sm" color="negative" />
                  </q-item-section>
                  <q-item-section> 删除 </q-item-section>
                </q-item>
              </q-list>
            </q-menu>
          </q-btn>
        </list-edit-big>
      </transition-fade>
      <!--修改弹窗-->
      <point-edit-big
        ref="pointEdit"
        @createPoint="createPoint"
        @editPoint="editPoint"
        :need-switch="true"
        :switchStatus="switchStatus"
        @switchChange="(val) => (switchStatus = val)"
      />
    </div>
    <!--连接点列表-->
    <transition-fade>
      <list-show-small
        @mouseup="pixiMap.outStage"
        v-if="lineIsEdit && editType === 'edit'"
        @update="updateLine"
        @save="editPoint"
        :title="activePoint.name || ''"
        :optionsList="pointList"
        :selectedList="activePoint.connectedPose || []"
      />
    </transition-fade>
    <!--选项列表-->
    <q-toggle
      class="absolute text-space"
      :class="ui.modelClass"
      style="top: 210px; right: 0; border-radius: 25px 0 0 25px"
      v-model="lineIsEdit"
      :label="$t('MapEdit.连线编辑')"
      @mouseup="pixiMap.outStage"
      v-show="editType === 'edit'"
    />
    <!--提示窗口-->
    <transition-fade>
      <notice-in-small
        @mouseup="pixiMap.outStage"
        v-show="editMode === 'relocate' && mode !== 'manual'"
        :text="$t('MapEdit.请选择点位将设备定位至该点处')"
        style="top: 200px"
      />
    </transition-fade>
    <q-list
      bordered
      class="absolute text-space"
      :class="ui.modelClass"
      style="top: 210px; right: 0; border-radius: 15px 0 0 15px"
      v-show="editType === 'editPolygon'"
    >
      <q-item class="text-h6" style="border-bottom: 1px solid white">
        {{
          activePoint.name
            ? $t("MapEdit.编辑") + ":" + activePoint.name
            : $t("MapEdit.添加安全区")
        }}</q-item
      >
      <q-item>
        <q-toggle :label="$t('MapEdit.删除原点')" v-model="deleteState"
      /></q-item>
      <q-item>
        <q-toggle :label="$t('MapEdit.添加原点')" v-model="addPolygon"
      /></q-item>
      <q-item>
        <q-btn
          no-caps
          :label="$t('MapEdit.删除')"
          @click="removePolygon"
          class="full-width"
          color="red"
          outline
      /></q-item>
      <q-item>
        <q-btn
          no-caps
          :label="$t('MapEdit.保存')"
          @click="savePolygon"
          class="full-width"
          color="secondary"
          outline
      /></q-item>
      <q-item>
        <q-btn
          no-caps
          :label="$t('MapEdit.退出')"
          @click="exitPolygon"
          class="full-width"
          color="primary"
          outline
      /></q-item>
    </q-list>
    <q-toggle
      no-caps
      class="absolute text-space"
      :class="ui.modelClass"
      v-model="keyboardMove"
      v-show="
        editMode !== 'polygon' &&
        showRobot &&
        useFunctionsStore().mode === 'remote'
      "
      style="top: 280px; right: 0; border-radius: 25px 0 0 25px"
      label="键盘移动"
    >
    </q-toggle>
    <create-qr-code ref="qrCodeRef" />
    <point-relocate ref="pointRelocates" @relocateSave="relocateSave" />
    <robot-relocate ref="robotRelocates" @update="editMode = ''" />
  </div>
</template>

<script setup>
import {
  computed,
  onBeforeMount,
  onMounted,
  onUnmounted,
  ref,
  watch,
  provide,
} from "vue";
import { api } from "boot/axios";
import { useQuasar } from "quasar";
import { useRoute } from "vue-router";
import { useAPIStore } from "stores/api";
import { useFunctionsStore } from "stores/functions";
import { useUiStore } from "stores/ui";
import * as PIXI from "pixi.js";
import PixiMap from "src/utils/PixiMap";
import RosClient from "src/utils/rosClient";
import { isConnected, status } from "src/utils/deviceWs";
import TransitionFade from "components/animations/Fade.vue";
import ListEditSmall from "components/map/ListEditSmall.vue";
import InputInSmall from "components/map/InputInSmall.vue";
import ListShowSmall from "components/map/ListShowSmall.vue";
import NoticeInSmall from "components/map/NoticeInSmall.vue";
import ListEditBig from "components/map/ListEditBig.vue";
import PointEditBig from "components/map/PointEditBig.vue";
import { useI18n } from "vue-i18n";
import CreateQrCode from "components/RemoteControl/CreateQrCode.vue";
// 手动重定位组件使用了老前端
import PointRelocate from "components/rosMapRemote/PointRelocate.vue";
import RobotRelocate from "components/map/RobotRelocate.vue";

const t = useI18n().t;
const $q = useQuasar();
const ui = useUiStore();
const route = useRoute();
const pixiMap = PixiMap();
const rosClient = RosClient();
const mapDiv = ref(); //  地图dom
const pointInSmall = ref(); //  pointList dom
const pointInBig = ref(); //  pointList dom
const pointEdit = ref(); //  pointEdit dom
const showRobot = computed(() => status.value.mapID === mapId.value); // 是否显示机器人
const mapId = ref("");
const pointSourceList = ref([]); //  点位源数据列表
const pointList = ref([]); //  点位列表（配合pointSourceList便于用户修改后想取消修改）
const polygonList = ref([]); //  安全区数据列表
const oldPolygonList = ref([]); //  旧安全区数据列表
const activePoint = ref({}); //  所选点位
const listTitle = ref(""); // 当前列表名称
const editMode = ref(""); //  当前编辑模式 point：点位编辑;polygon: 安全区编辑
const editType = ref(""); //  当前编辑类型 add：新建  edit：编辑
const lineIsEdit = ref(false); //  是否开启编辑连线
const switchStatus = ref(false); //  是否默认开启编辑弹窗
const deleteState = ref(false); //  是否删除安全区点
const addPolygon = ref(false); //  是否新增安全区点
const qrCodeRef = ref();
const keyboardMove = ref(false);

const optionsMode = [
  { label: "设备定位", value: "relocate" },
  { label: "手动定位", value: "manual" },
];
const mode = ref("relocate");

const robotRelocates = ref(); // 老前端机器人手动重定位
const pointRelocates = ref(); // 老前端手动重定位
const isRelocating = ref(false);
provide("isRelocating", isRelocating);
provide("robotPose", rosClient.robotPose);

provide("pixiMap", pixiMap);
// ------生命周期----------------------------------------------------------------------
onBeforeMount(() => {
  mapId.value = route.query.id;
});

onMounted(() => {
  //  判断是否为机器人端
  if (
    useFunctionsStore().mode === "device" ||
    useFunctionsStore().mode === "remote"
  ) {
    rosClient.createWs();
    setKeyboard();
  }
  initPixi();
});

onUnmounted(() => {
  rosClient.closeWs();
  pixiMap.destroyStage();
  document.onkeyup = null;
  document.onkeydown = null;
});

// ------监听-------------------------------------------------------------------------
// 监听amr状态，判断是否显示机器人
watch(showRobot, (val) => {
  if (val) loadRobot();
});

// 监听激光雷达进行更新
watch(rosClient.scanPose, (value) => {
  pixiMap.drawScan(value);
});

// 监听设备位置
watch(rosClient.robotPose, (value) => {
  if (!isRelocating.value) {
    pixiMap.updateRobot(value);
  }
});

//  监听编辑模式
watch(editMode, (value) => {
  if (value === "point") {
    //  点位编辑
    listTitle.value = t("MapEdit.点位设定");
    // 覆写点位的点击事件
    pixiMap.clickPoint = choosePoint;
  } else if (value === "relocate") {
    if (mode.value === "manual") {
      console.log("111");
      robotRelocates.value.show();
    } else {
      listTitle.value = t("MapEdit.设备定位");
      // 覆写点位的点击事件
      pixiMap.clickPoint = relocateRobotToPose;
    }
  } else if (value === "polygon") {
    listTitle.value = t("MapEdit.安全区域");
    pixiMap.clickPolygon = choosePolygon;
    creatorPolygons();
  } else {
    //  退出编辑模式
    //  退出编辑模式,判断是否编辑了安全区,编辑后重画
    if (editType.value === "editPolygon") {
      pixiMap.clearPolygon();
      pixiMap.drawPolygon(polygonList.value);
      pixiMap.clickPolygon = () => {};
      addPolygon.value = false;
      deleteState.value = false;
      pixiMap.viewLocking = false;
      pixiMap.stageMoveState = false;
    }
    editType.value = "";
    lineIsEdit.value = false;
    pixiMap.clickPoint = () => {};
    pixiMap.highlight(""); //  高亮
    activePoint.value = {};
  }
});

//  是否编辑连线
watch(lineIsEdit, (value) => {
  if (value) {
    // 覆写点位的点击事件
    pixiMap.clickPoint = editLine;
  } else {
    // 覆写点位的点击事件
    pixiMap.clickPoint = choosePoint;
  }
});
// 是否要添加安全区点
watch(addPolygon, (value) => {
  if (value) deleteState.value = false;
  pixiMap.polygonState = value;
});
// 是否删除安全区点
watch(deleteState, (value) => {
  if (value) addPolygon.value = false;
});
// ------地图渲染----------------------------------------------------------------------
// 创建画布
function initPixi() {
  mapDiv.value.innerHTML = "";
  pixiMap.div = mapDiv.value;
  pixiMap.stage = pixiMap.createStage(mapDiv.value);
  initImg();
}

// 初始化素材
function initImg() {
  const poseImg = new Image();
  poseImg.src = "map/pose.png";
  window.URL.revokeObjectURL(poseImg.src);
  poseImg.onload = () => {
    pixiMap.setPointStyle({ img: poseImg });
    loadMap();
  };
}

// 加载地图
function loadMap() {
  // 根据地图id获取地图信息
  api.get(useAPIStore().mapUrl + "map/id/" + mapId.value).then((res) => {
    const mapImage = new Image();
    mapImage.src =
      "data:image/" +
      (res.data.format === "landmark" ? "png" : res.data.format) +
      ";base64," +
      res.data.mapBase64;
    window.URL.revokeObjectURL(mapImage.src);
    // 地图图片加载成功
    mapImage.onload = () => {
      // 渲染地图
      pixiMap.map = pixiMap.createMap({
        resolution: res.data.resolution,
        x: res.data.x,
        y: res.data.y,
        img: mapImage,
      });
      // 加载点位
      loadRoutes();
      // 加载虚拟墙
      loadPolygons();
      pixiMap.updateStage();
    };
  });
}

// 加载机器人
function loadRobot() {
  const robotImg = new Image();
  robotImg.src = "map/arrow.png";
  window.URL.revokeObjectURL(robotImg.src);
  // 机器人图片加载成功
  robotImg.onload = () => {
    // 渲染机器人
    pixiMap.robot = pixiMap.createRobot({ img: robotImg });
    // 更新机器人位置
    rosClient.subscribe("/robot_pose");
    // 订阅激光雷达数据
    rosClient.subscribe("/scan_simplified");
    pixiMap.updateStage();
    // 加载完毕后，视角落到机器人上
    setTimeout(() => {
      pixiMap.focus();
    }, 500);
  };
}

// 加载点位
function loadRoutes() {
  // 根据地图id获取点位信息
  api
    .get(useAPIStore().mapUrl + "mapPose/ros/mapID/" + mapId.value)
    .then((res) => {
      pointSourceList.value = res.data;
      //  从源数据获取点位列表
      pointList.value = JSON.parse(JSON.stringify(pointSourceList.value));
      // 点位名常显
      pixiMap.pointNameShow = true;
      // 绘制点位路线
      pixiMap.drawRail(pointSourceList.value);
    });
}

// 加载安全区
function loadPolygons() {
  api
    .get(useAPIStore().mapUrl + "new/polygon/mapID/" + mapId.value)
    .then((res) => {
      if (res.data.code === 200) {
        polygonList.value = res.data.data;
        oldPolygonList.value = JSON.parse(JSON.stringify(polygonList.value));
        pixiMap.drawPolygon(polygonList.value);
      }
    });
}

// ------事件函数----------------------------------------------------------------------
// 重载点位
function load() {
  $q.notify({ message: t("MapEdit.重载路线成功"), type: "positive" });
  api
    .get(useAPIStore().centerUrl + "navigation/reset/" + mapId.value)
    .then((rs) => {
      if (rs.data === "done") {
        // $q.notify({ message: '调度系统点位已重载', type: 'positive' })
      } else {
        $q.notify({
          message: t("MapEdit.调度系统点位重载失败"),
          type: "negative",
        });
      }
    });
}
// 退出编辑
function exit() {
  if (editMode.value === "point") {
    if (
      JSON.stringify(pointList.value) !== JSON.stringify(pointSourceList.value)
    ) {
      $q.dialog({
        dark: ui.isDark,
        title: t("MapEdit.退出编辑"),
        message: `<span class="text-space">${t(
          "MapEdit.数据发生改动是否需要保存"
        )}</span>`,
        html: true,
        ok: t("MapEdit.保存"),
        cancel: t("MapEdit.不保存"),
      })
        .onOk(() => {
          api
            .put(
              useAPIStore().mapUrl + "new/mapPose/ros/" + mapId.value,
              pointList.value
            )
            .then((res) => {
              if (res.data.code === 200) {
                editMode.value = "";
                $q.notify({
                  message: t("MapEdit.保存成功"),
                  color: "positive",
                  position: "top-right",
                });
                load();
              } else {
                $q.notify({
                  message: t("MapEdit.保存失败"),
                  color: "negative",
                  position: "top-right",
                });
              }
            })
            .catch(() => {
              $q.notify({
                message: t("MapEdit.保存失败"),
                color: "negative",
                position: "top-right",
              });
            });
        })
        .onCancel(() => {
          editMode.value = "";
          pointList.value = JSON.parse(JSON.stringify(pointSourceList.value));
          // 绘制点位路线
          pixiMap.drawRail(pointSourceList.value);
        });
    } else {
      editMode.value = "";
    }
  } else if (editMode.value === "polygon") {
    pixiMap.clickPolygon = () => {};
    editMode.value = "";
    addPolygon.value = false;
    deleteState.value = false;
    pixiMap.viewLocking = false;
    pixiMap.stageMoveState = false;
  } else {
    editMode.value = "";
  }
}

// 点击选项
function choose(item) {
  if (editMode.value === "point") {
    // lineIsEdit.value = false
    pixiMap.lookAt(pixiMap.getPoint(item.id));
    choosePoint(item);
    if (switchStatus.value) pointEdit.value.show(activePoint.value);
  } else if (editMode.value === "relocate") {
    relocateRobotToPose(item);
    pixiMap.lookAt(pixiMap.getPoint(item.id));
  } else if (editMode.value === "polygon") {
    // 安全区聚焦
    pixiMap.lookPolygon(item);
    editType.value = "editPolygon";
    choosePolygon(item);
  }
}

// 点击添加
function add() {
  if (editMode.value === "point" || editMode.value === "relocate") {
    if (showRobot.value) {
      editType.value = "add";
      activePoint.value = {};
      pointEdit.value.show();
    } else {
      $q.dialog({
        dark: ui.isDark,
        title: t("MapEdit.无法创建点位"),
        html: true,
        message: t(
          "MapEdit.存在以下两种可能设备未连接此地图并非设备当前已选地图"
        ),
        ok: t("MapEdit.知道了"),
      });
    }
  } else {
    // 清空地图上所有安全区数据
    pixiMap.clearPolygon();
    pixiMap.drawPolygon(JSON.parse(JSON.stringify(oldPolygonList.value)));
    activePoint.value = {
      newPolygon: [],
      polygon: [],
      id: "text",
    };
    editType.value = "editPolygon";
    addPolygon.value = true;
  }
}

// 选择点位
function choosePoint(point) {
  editType.value = "edit";
  activePoint.value = point;
  pixiMap.highlight(point.id); //  高亮
  const index = pointList.value.findIndex((item) => item.id === point.id);
  pointInBig.value.scrollTo(index);
}

//  编辑点位的连线
function editLine(point) {
  //  点击当前点，无作为
  if (activePoint.value.id === point.id) return;
  const index = pointList.value.findIndex(
    (item) => item.id === activePoint.value.id
  );
  //  判断连接点中是否含有点击点
  if (activePoint.value.connectedPose.indexOf(point.id) < 0) {
    pointList.value[index].connectedPose.push(point.id);
  } else {
    pointList.value[index].connectedPose.splice(
      activePoint.value.connectedPose.indexOf(point.id),
      1
    );
  }
  activePoint.value.connectedPose = pointList.value[index].connectedPose;
  pixiMap.drawRail(pointList.value);
}

// 新建点位
function createPoint(data) {
  if (!data.value.name) {
    $q.notify({
      message: t("MapEdit.点位名称未填写"),
      color: "negative",
      position: "top-right",
    });
  } else {
    $q.dialog({
      dark: ui.isDark,
      title: t("MapEdit.创建点位"),
      message: t("MapEdit.将在机器人处创建点位") + data.value.name,
      ok: t("ok"),
      cancel: t("cancel"),
    }).onOk(() => {
      const params = {
        name: data.value.name,
        type: data.value.type,
        turnable: data.value.turnable,
        mapID: mapId.value,
        pose: rosClient.robotPose.value,
      };
      api.post(useAPIStore().mapUrl + "mapPose/ros", params).then(() => {
        load();
        pointEdit.value.close();
        //  重新加载路径
        loadRoutes();
        editType.value = "";
        pointInSmall.value.scrollTo("end");
        $q.notify({
          message: t("MapEdit.点位") + data.value.name + t("MapEdit.创建成功"),
          color: "positive",
          position: "top-right",
        });
      });
    });
  }
}

// 保存点位
function editPoint(data) {
  if (data) {
    activePoint.value.name = data.value.name;
    activePoint.value.type = data.value.type;
    activePoint.value.turnable = data.value.turnable;
    activePoint.value.pose.position.x = data.value.pose.position.x;
    activePoint.value.pose.position.y = data.value.pose.position.y;
  }
  api.put(useAPIStore().mapUrl + "mapPose/ros", activePoint.value).then(() => {
    load();
    pointEdit.value.close();
    loadRoutes();
    lineIsEdit.value = false;
    $q.notify({
      message:
        t("MapEdit.点位") + activePoint.value.name + t("MapEdit.修改成功"),
      color: "positive",
      position: "top-right",
    });
  });
}

// 重定位点位
function relocatePoint(point) {
  $q.dialog({
    dark: ui.isDark,
    title: t("MapEdit.重定位点位"),
    message: "选择重定位模式 !",
    // message: t('MapEdit.是否将点位') + point.name + t('MapEdit.重定位至设备处'),
    options: {
      type: "radio",
      model: "manual",
      items: [
        { label: "重定位至设备处", value: "voluntarily" },
        { label: "手动重定位", value: "manual" },
      ],
    },
    ok: t("ok"),
    cancel: t("cancel"),
  }).onOk((data) => {
    if (data === "voluntarily") {
      point.pose = rosClient.robotPose.value;
      api.put(useAPIStore().mapUrl + "mapPose/ros", point).then(() => {
        load();
        //  重新加载路径
        loadRoutes();
        editType.value = "";
        $q.notify({
          message: t("MapEdit.点位") + point.name + t("MapEdit.重定位成功"),
          color: "positive",
          position: "top-right",
        });
      });
    } else {
      pointRelocates.value.show(point, pointList.value);
      editMode.value = "";
    }
  });
}

// 手动重定位后保存数据
function relocateSave(list) {
  api
    .put(useAPIStore().mapUrl + "new/mapPose/ros/" + mapId.value, list)
    .then((res) => {
      if (res.data.code === 200) {
        pointList.value = list;
        pointSourceList.value = pointList.value;
        editMode.value = "point";
        $q.notify({
          message: t("MapEdit.保存成功"),
          color: "positive",
          position: "top-right",
        });
        load();
      } else {
        $q.notify({
          message: t("MapEdit.保存失败"),
          color: "negative",
          position: "top-right",
        });
      }
    })
    .catch(() => {
      $q.notify({
        message: t("MapEdit.保存失败"),
        color: "negative",
        position: "top-right",
      });
    });
}

// 删除点位
function deletePoint(point) {
  $q.dialog({
    dark: ui.isDark,
    title: t("MapEdit.删除点位"),
    message: t("MapEdit.是否删除点位") + point.name,
    ok: t("ok"),
    cancel: t("cancel"),
  }).onOk(() => {
    api.delete(useAPIStore().mapUrl + "mapPose/ros/" + point.id).then(() => {
      load();
      //  重新加载路径
      loadRoutes();
      editType.value = "";
      lineIsEdit.value = false;
      $q.notify({
        message: t("MapEdit.点位") + point.name + t("MapEdit.删除成功"),
        color: "positive",
        position: "top-right",
      });
    });
  });
}

// 更新连线
function updateLine(list) {
  //  获取当前激活点在list中的位置
  activePoint.value.connectedPose = list;
  const index = pointList.value.findIndex(
    (item) => item.id === activePoint.value.id
  );
  pointList.value[index].connectedPose = activePoint.value.connectedPose;
  pixiMap.drawRail(pointList.value);
}

const poseWithCovarianceStamped = ref({
  header: { seq: 0, stamp: 0, frame_id: "map" },
  pose: {
    pose: {
      position: { x: 0, y: 0, z: 0 },
      orientation: { x: 0, y: 0, z: 0, w: 1 },
    },
    covariance: [
      0.01, 0, 0, 0, 0, 0, 0, 0.01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.1,
    ],
  },
});

// 重定位设备
function relocateRobotToPose(point) {
  //  禁止画布拖动，需要加一点延迟
  setTimeout(() => pixiMap.outStage(), 100);
  $q.dialog({
    dark: ui.isDark,
    title: t("MapEdit.设备重定位"),
    style: { top: "-250px" },
    message:
      t("MapEdit.是否要将机器人的当前位置和方向校准至") + point.name + "？",
    ok: t("ok"),
    cancel: t("cancel"),
    persistent: true,
  }).onOk(() => {
    poseWithCovarianceStamped.value.header.seq++;
    poseWithCovarianceStamped.value.pose.pose = point.pose;
    api
      .post(
        useAPIStore().amrUrl + "ros/call",
        [poseWithCovarianceStamped.value],
        { params: { service: "/set_robot_pose" } }
      )
      .then((rs) => {
        if (rs.data.values.success) {
          $q.notify({ type: "positive", message: "重定位成功" });
        } else {
          $q.notify({ type: "warning", message: "重定位失败" });
        }
      });
  });
}

// 选择安全区
function choosePolygon(point) {
  // if (JSON.stringify(oldPolygonList.value) !== JSON.stringify(polygonList.value)) {
  //   exitPolygon()
  //   return
  // }
  editType.value = "editPolygon";
  // 清空地图上所有安全区数据
  pixiMap.clearPolygon();
  pixiMap.drawPolygon(JSON.parse(JSON.stringify(oldPolygonList.value)));
  activePoint.value = point;
  pixiMap.polygonContainer.removeChild(
    pixiMap.polygonContainer.getChildByName(point.id)
  );
  pixiMap.polygonContainer.removeChild(
    pixiMap.polygonContainer.getChildByName("dotContainer")
  );
  newPolygon(activePoint.value);
}
// 添加安全区点位
function newPolygon(data) {
  // 判断是否为删除模式只有删除模式下会清空点位图层
  if (deleteState.value) {
    pixiMap.polygonContainer.removeChild(
      pixiMap.polygonContainer.getChildByName("dotContainer")
    );
  }
  // 显示创建点的对象坐标 [{x,y},...]
  const p = data.polygon;
  // 点图层
  const container = new PIXI.Container();
  // 添加在安全区图层
  pixiMap.polygonContainer.addChild(container);
  container.name = "dotContainer";
  p.forEach((item, index) => {
    // 创建点
    const dot = pixiMap.safetyDot(item);
    dot.id = index;
    // 鼠标显示为小手
    dot.cursor = "pointer";
    // 点击事件
    dot.onpointerdown = () => {
      dot.tint = "0xFF0000";
      dot.alpha = 0.8;
      // // 切换全局事件
      pixiMap.stageMoveState = true;
      // 是否能拖动
      pixiMap.viewLocking = true;
      // 点位是否选中的状态
      dot.state = true;
      // 是否删除点
      if (deleteState.value) {
        dot.state = false;
        $q.dialog({
          title: t("MapEdit.提示"),
          message: t("MapEdit.您确定删除嘛"),
          cancel: t("MapEdit.取消"),
          ok: t("MapEdit.确认"),
          persistent: true,
        })
          .onOk(() => {
            // 删除点对象里数据
            activePoint.value.newPolygon.splice(
              activePoint.value.newPolygon.indexOf(dot.x),
              1
            );
            activePoint.value.newPolygon.splice(
              activePoint.value.newPolygon.indexOf(dot.y),
              1
            );
            activePoint.value.polygon = handleArr(activePoint.value.newPolygon);
            // 重新创建点位
            newPolygon(activePoint.value);
            // 重新画线
            polygonLine(activePoint.value);
          })
          .onCancel(() => {
            dot.tint = "0xFF0000";
            dot.alpha = 0.3;
            pixiMap.viewLocking = false;
            dot.state = false;
          });
      }
    };
    // 按下
    dot.onpointermove = () => {
      // 删除不可拖动
      if (deleteState.value) return;
      pixiMap.stagePointermove = (e) => {
        // 只有选中才可拖动
        if (dot.state) {
          const pos = pixiMap.globalToRos(e.data.global.x, e.data.global.y);
          // 修改点位坐标
          dot.x = pos.x;
          dot.y = -pos.y;
          activePoint.value.polygon[index].x = pos.x;
          activePoint.value.polygon[index].y = -pos.y;
          const newPolygon = [];
          activePoint.value.polygon.forEach((item) => {
            newPolygon.push(item.x);
            newPolygon.push(item.y);
          });
          // 获取修改后坐标系的数组
          activePoint.value.newPolygon = newPolygon;
          // state
          polygonLine(activePoint.value);
        }
      };
    };
    // 松开
    dot.onpointerup = () => {
      pixiMap.stageMoveState = false;
      pixiMap.viewLocking = false;
      dot.state = false;
      dot.tint = "0xFF0000";
      dot.alpha = 0.3;
    };
    // 添加点位
    container.addChild(dot);
  });
  polygonLine(data);
}
// 将所有的数组切换成{x,y}
function handleArr(arr, n = 2) {
  const res = [];
  for (let i = 0; i < arr.length - 1; i += 2) {
    const index = Math.floor(i / n);
    res[index] = {
      x: arr[i],
      y: arr[i + 1],
    };
  }
  return res;
}
// 安全区画线
function polygonLine(data) {
  // 删除当前安全区连线
  pixiMap.polygonContainer.removeChild(
    pixiMap.polygonContainer.getChildByName(data.id)
  );
  const pos = new PIXI.Graphics();
  pos.lineStyle(pixiMap.polygonSize, pixiMap.polygonColor);
  pos.name = data.id;
  pos.drawPolygon(data.newPolygon);
  pixiMap.polygonContainer.addChild(pos);
}
// 创建安全区
function creatorPolygons() {
  pixiMap.clickDot = (e) => {
    if (addPolygon.value) {
      // 获取ros地图坐标
      const pos = pixiMap.globalToRos(e.data.global.x, e.data.global.y);
      // 赋值安全区数据
      activePoint.value.polygon.push({ x: pos.x, y: -pos.y });
      activePoint.value.newPolygon.push(pos.x);
      activePoint.value.newPolygon.push(-pos.y);
      pixiMap.polygonContainer.removeChild(
        pixiMap.polygonContainer.getChildByName(activePoint.value.id)
      );
      pixiMap.polygonContainer.removeChild(
        pixiMap.polygonContainer.getChildByName("dotContainer")
      );
      newPolygon(activePoint.value);
    }
  };
}
// 保存安全区和修改安全区
function savePolygon() {
  $q.dialog({
    title: activePoint.value.name
      ? t("MapEdit.修改安全区")
      : t("MapEdit.保存安全区"),
    message: t("MapEdit.请输入安全区的名称"),
    prompt: {
      model: activePoint.value.name ? activePoint.value.name : "",
      type: "text",
    },
    ok: { label: t("MapEdit.确认"), class: "text-bold", flat: true },
    cancel: {
      label: t("MapEdit.取消"),
      class: "text-bold",
      color: "secondary",
      flat: true,
    },
    persistent: true,
  }).onOk((data) => {
    activePoint.value.name = data;
    activePoint.value.mapID = mapId.value;
    activePoint.value.type = "wall";
    if (activePoint.value.id === "text") {
      delete activePoint.value.id;
      api
        .post(useAPIStore().mapUrl + "new/polygon", activePoint.value)
        .then((res) => {
          if (res.data.code === 200) {
            load();
            $q.notify({
              message: t("MapEdit.安全区保存成功"),
              type: "positive",
              position: "bottom-right",
            });
            empty();
          } else {
            $q.notify({
              message: t("MapEdit.安全区保存失败"),
              type: "negative",
              position: "bottom-right",
            });
            activePoint.value.id = "text";
          }
        })
        .catch(() => {
          $q.notify({
            message: t("MapEdit.接口请求异常"),
            type: "negative",
            position: "bottom-right",
          });
          activePoint.value.id = "text";
        });
    } else {
      api
        .put(useAPIStore().mapUrl + "polygon", activePoint.value)
        .then((res) => {
          if (res.data === "update") {
            load();
            empty();
            $q.notify({
              message: t("MapEdit.安全区修改成功"),
              type: "positive",
              position: "bottom-right",
            });
          } else {
            $q.notify({
              message: t("MapEdit.安全区修改失败"),
              type: "negative",
              position: "bottom-right",
            });
          }
        })
        .catch(() => {
          $q.notify({
            message: t("MapEdit.接口请求异常"),
            type: "negative",
            position: "bottom-right",
          });
        });
    }
  });
}
// 删除安全区
function removePolygon() {
  $q.dialog({
    title: t("MapEdit.提示"),
    message: activePoint.value.name
      ? t("MapEdit.您确定删除") + activePoint.value.name + t("MapEdit.安全区嘛")
      : t("MapEdit.您确定删除该安全区"),
    cancel: t("MapEdit.取消"),
    ok: t("MapEdit.确认"),
    persistent: true,
  }).onOk(() => {
    if (activePoint.value.id === "text") {
      empty();
    } else {
      api
        .delete(useAPIStore().mapUrl + "polygon/" + activePoint.value.id)
        .then((res) => {
          if (res.data === "delete") {
            load();
            $q.notify({
              message: t("MapEdit.安全区删除成功"),
              type: "positive",
              position: "bottom-right",
            });
            empty();
          } else {
            $q.notify({
              message: t("MapEdit.安全区删除失败"),
              type: "negative",
              position: "bottom-right",
            });
          }
        })
        .catch(() => {
          $q.notify({
            message: t("MapEdit.接口请求异常"),
            type: "negative",
            position: "bottom-right",
          });
        });
    }
  });
}
// 清空所有安全区状态
function empty() {
  // 恢复状态
  addPolygon.value = false;
  deleteState.value = false;
  pixiMap.viewLocking = false;
  pixiMap.stageMoveState = false;
  pixiMap.clearPolygon();
  loadPolygons();
  activePoint.value = {
    newPolygon: [],
    polygon: [],
    id: "text",
  };
  editType.value = "";
}
// 退出安全区
function exitPolygon() {
  if (
    JSON.stringify(oldPolygonList.value) !== JSON.stringify(polygonList.value)
  ) {
    $q.dialog({
      title: t("MapEdit.提示"),
      message: t("MapEdit.是否退出安全区编辑模式退出后修改的数据将会失效"),
      cancel: t("MapEdit.退出"),
      ok: t("MapEdit.保存"),
      persistent: true,
    })
      .onOk(() => {
        savePolygon();
        load();
      })
      .onCancel(() => {
        empty();
      });
  } else {
    empty();
  }
}
//  显示二维码
function showQrCode() {
  if (isConnected.value) {
    if (status.value.network) {
      qrCodeRef.value.show(
        "http://" +
          status.value.network.IPv4 +
          "/#/RemoteControl" +
          "?id=" +
          mapId.value
      );
    } else {
      $q.notify({ message: t("MapCreate.局域网未连接"), type: "negative" });
    }
  } else {
    $q.notify({ message: t("MapCreate.设备未连接"), type: "negative" });
  }
}
/* --------------------------------------键盘移动--------------------------------------------------- */
const twist = ref({
  linear: { x: 0, y: 0, z: 0 },
  angular: { x: 0, y: 0, z: 0 },
});
function pubVel(x, z) {
  twist.value.linear.x = x;
  twist.value.angular.z = z;
  rosClient.publish("/device_send_raw", "SET_STATE,NORMAL｜～");
  rosClient.publish("/web/cmd_vel", twist.value);
}
const linear = ref(0);
const angular = ref(0);
function setKeyboard() {
  document.onkeydown = (e) => {
    if (keyboardMove.value) {
      switch (e.keyCode) {
        case 38:
          linear.value = 0.4;
          angular.value = 0;
          pubVel(linear.value, angular.value);
          break;
        case 40:
          linear.value = -0.4;
          angular.value = 0;
          pubVel(linear.value, angular.value);
          break;
        case 37:
          angular.value = 0.2;
          linear.value = 0;
          pubVel(linear.value, angular.value);
          break;
        case 39:
          angular.value = -0.2;
          linear.value = 0;
          pubVel(linear.value, angular.value);
          break;
      }
    }
  };
  document.onkeyup = (e) => {
    if (keyboardMove.value) {
      switch (e.keyCode) {
        case 38:
        case 40:
          linear.value = 0;
          break;
        case 37:
        case 39:
          angular.value = 0;
          break;
      }
    }
  };
}
</script>
